# This is a youtube-dl youtube song downloader. It uses both youtube-dl
# for actual download and the invidious API for fetching info about the
# song. GPLv3+

import os
from subprocess import *
import json
import random
import urllib.request
import urllib.parse

dfolder = "downloads"

def difference(x,y):
    if x > y:
        return x - y
    else:
        return y - x

def fetch_info(videoId):

    # This function will output the info about our song.
    try:
        url = "https://invidious.namazso.eu/api/v1/videos/"+videoId
        req = urllib.request.Request(url, data=None)
        f = urllib.request.urlopen(req)
        data = json.loads(f.read().decode('utf-8'))
    except:
        url = "https://yewtu.be/api/v1/videos/"+videoId
        req = urllib.request.Request(url, data=None)
        f = urllib.request.urlopen(req)
        data = json.loads(f.read().decode('utf-8'))
        
        
    return data

def search(query):

    # This function will search on youtube a query.

    url = "https://invidious.namazso.eu/api/v1/search/?q="+urllib.parse.quote_plus(query)
    req = urllib.request.Request(url, data=None)
    f = urllib.request.urlopen(req)
    data = json.loads(f.read().decode('utf-8'))

    return data
    

def try_download(videoId, filename):
    
    # This fucntion will try download the song via youtube-dl

    #print("Trying to download", videoId)
    
    # Making sure that the download folder exists
    try:
        os.mkdir(dfolder)
    except:
        pass
    
    try:
        # We are using subbrocess.check_output here to catch errors.
        check_output(["youtube-dl",
                     "https://youtube.com/watch?v="+videoId,
                      "-x",
                     "--output",
                      dfolder+"/"+str(filename)+".%(ext)s"])
        return True
    except Exception as e:
        print("youtube-dl error", e)
        return False

def insure_song(videoId, filename):

    # This function will insure a song is downloaded.

    songInfo = fetch_info(videoId)

    #print("Song", songInfo["title"], "by", songInfo["author"], "direct attempt.")
    
    # First we will try downloading the song as is.
    if try_download(videoId, filename):
        #print("Worked!")
        return True
    else:
        #print("Failed! Trying similar...")
        
        # If it failed we are going to try downloading a similar song.

        titleblacklist = ["cover", "react", "review", "remix", "acoustic", "teaser", "live"]

        query = songInfo["title"]
        if " - Topic" in songInfo["author"]:
            query = songInfo["author"].replace(" - Topic", "")+" "+query
        
        others = search(query)

        for song in others:

            # Chekcing that it's a video
            if song["type"] != "video":
                print("Skipped:", song["title"], "because not a video." )
                continue
            
            # Checking if the song is a cover or a remix
            
            cont = False
            for i in titleblacklist:
                if i.lower() in song["title"].lower():
                    cont = i
                    break
            if cont:
                #print("Skipped:", song["title"], "because", cont )
                continue

            # Chekcing the length of the song to be roughly the original

            if difference(song["lengthSeconds"], songInfo["lengthSeconds"]) > 60:
                print("Skipped:", song["title"], "because length is too different." )
                continue

            #print("Trying to download", song["title"])
            
            if try_download(song["videoId"], filename):
                return "Got Similar"

        return False

